<?php

namespace App\Utils;

use Exception;

class AesCrypto
{
    /**
     * 加密算法及模式
     * @var string
     */
    private $cipher = 'aes-256-cbc';

    /**
     * 加密密钥
     * @var string
     */
    private $key;

    /**
     * 构造函数
     * @param string $key 原始密钥
     * @param int $keyLength 密钥长度(字节)，aes-256对应32字节
     * @param string $padChar 密钥补全字符
     * @throws Exception
     */
    public function __construct(string $key, int $keyLength = 32, string $padChar = "\0") {
        // 补全密钥至指定长度
        $this->key = str_pad($key, $keyLength, $padChar, STR_PAD_RIGHT);

        // 验证密钥长度
        if (strlen($this->key) !== $keyLength) {
            throw new Exception("密钥长度不符合要求，需为{$keyLength}字节");
        }
    }

    /**
     * 加密数据
     * @param string $data 待加密数据
     * @return string 加密后的base64字符串
     */
    public function encrypt(string $data): string {
        // 生成随机IV(初始向量)
        $ivLength = openssl_cipher_iv_length($this->cipher);
        $iv = openssl_random_pseudo_bytes($ivLength);

        // 执行加密
        $encrypted = openssl_encrypt(
            $data,
            $this->cipher,
            $this->key,
            OPENSSL_RAW_DATA,
            $iv
        );

        // 拼接IV和密文，Base64编码后返回
        return base64_encode($iv . $encrypted);
    }

    /**
     * 解密数据
     * @param string $encryptedData 加密后的base64字符串
     * @return string|false 解密结果或false
     */
    public function decrypt(string $encryptedData) {
        // Base64解码
        $decoded = base64_decode($encryptedData);
        if ($decoded === false) {
            return false;
        }

        // 提取IV和密文
        $ivLength = openssl_cipher_iv_length($this->cipher);
        $iv = substr($decoded, 0, $ivLength);
        $encrypted = substr($decoded, $ivLength);

        // 执行解密
        return openssl_decrypt(
            $encrypted,
            $this->cipher,
            $this->key,
            OPENSSL_RAW_DATA,
            $iv
        );
    }
}
